//@author A0097972J
package logic;

import gui.IUserInterface;

import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import common.AttributeType;
import common.Command;
import common.CommandType;
import common.Task;

/**
 * Confirm Command Handler class<br/>
 * This class contains all the logic for Confirm command, which will support the
 * confirmation for delete and update commands in general</br>
 */
public class ConfirmCommandHandler extends CommandHandler {

	private static final Logger logger = Logger.getLogger(ConfirmCommandHandler.class.getName());
	private final String INVAILD_ID = "\n Invalid/No such ID number";
	private final String NULL_TASK_ERROR = "\n No Task selected";

	public ConfirmCommandHandler(IUserInterface ui, String originalCommand, HashMap<AttributeType, String> attrList) {
		super(ui, originalCommand, attrList);
	}

	/**
	 * Needs to be explicitly called for the command to be started <br/>
	 * This method will first check for syntax error before executing the
	 * command <br/>
	 */
	public void start() {
		if (isSyntaxCorrect()) {
			int i = checkAndConvertInteger(_attrList.get(AttributeType.id));
			execute(i);
		} else {
			pushToHistoryAsNonExecutableCommand();
			writeToConsole(INVAILD_ID);
		}
	}

	//@author A0088498A
	/**
	 * Enforce that the id field is provided and the id value is a parse-able
	 * positive integer <br/>
	 * 
	 * @return true if the syntax is correct, otherwise false (when the id field
	 *         is null or the id value is not a parse-able positive integer)
	 */
	private boolean isSyntaxCorrect() {
		if (_attrList.get(AttributeType.id) == null) {
			return false;
		} else {
			int i = checkAndConvertInteger(_attrList.get(AttributeType.id));
			if (i < 1) {
				return false;
			}
			return true;
		}
	}

	//@author A0097972J
	/**
	 * Check and convert the String into a strict positive integer
	 * 
	 * @param str
	 *            to convert
	 * @return the converted number, -1 if cannot be converted or the convert
	 *         integer is not a strict positive number (i.e: > 0)
	 */
	private int checkAndConvertInteger(String str) {
		int tmpInt = -1;
		try {
			tmpInt = Integer.parseInt(str);
			if (tmpInt < 1) {
				tmpInt = -1;
			}
		} catch (Exception e) {
			// error in parsing the string
			tmpInt = -1;
		}
		return tmpInt;
	}

	/**
	 * Gets selected task from previous search result<br/>
	 * Determines the previous command is update or delete<br/>
	 * Execute the corresponding action<br/>
	 * 
	 * For delete confirmation:<br/>
	 * {@code confirm -id 1}
	 * 
	 * <br/>
	 * For update confirmation:<br/>
	 * {@code confirm -id 1 -name task -startingTime 20/03/2014 -endingTime 21/03/2014}
	 * 
	 * @param index
	 */
	private void execute(int index) {
		try {
			Command previousCommand = getPreviousCommand();
			Task selectedTask = getSelectedTask(index);

			CommandType cmdType = previousCommand.getType();
			if (selectedTask != null) {

				switch (cmdType) {

				case delete:
					DeleteCommandHandler deleteCmdHandler = new DeleteCommandHandler(_ui, _originalCommand, _attrList);
					deleteCmdHandler.deleteFromStorage(selectedTask);
					break;
				case update:
					String prvStatus = previousCommand.getTask().getStatus().toString();
					UpdateCommandHandler updateCmdHandler = new UpdateCommandHandler(_ui, _originalCommand, _attrList);
					if (prvStatus != null) {
						_attrList.put(AttributeType.status, prvStatus);
					} else {
						_attrList.put(AttributeType.status, selectedTask.getStatus().toString());
					}
					updateCmdHandler.updateStorage(selectedTask);
					break;
				default:
					break;
				}
			} else {
				writeToConsole(NULL_TASK_ERROR);
			}
		} catch (Exception e) {
			logger.log(Level.WARNING, e.getMessage(), e);
		}
	}

	/**
	 * Get the Task based on the index user provided and return it <br/>
	 * 
	 * @param i
	 *            the index of the Task, according to the previous search result
	 * @return indexed task
	 */
	private Task getSelectedTask(int i) {
		try {
			List<Task> previousResults = getStorage().getPreviousSearchResult();
			return previousResults.get(i - 1);
		} catch (IndexOutOfBoundsException e) {
			return null;
		}
	}

	/**
	 * Get previous command from History <br/>
	 * 
	 * @return command that previously execute in the History
	 */
	private Command getPreviousCommand() {

		return getHistory().recallCmd();
	}

}
